﻿// XmlVisualizer
// Copyright (C) 2009  Roman Betík - rbetik@gmail.com

// This program is free software; you can redistribute it and/or
// modify it under the terms of the GNU General Public License
// as published by the Free Software Foundation; either version 2
// of the License, or (at your option) any later version.

// This program is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
// GNU General Public License for more details.

// You should have received a copy of the GNU General Public License
// along with this program; if not, write to the Free Software
// Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA.

using System;
using System.Collections.Generic;
using System.Linq;

namespace XmlVisualizer.DiagramDesigner {
	internal class SelectionService {
		#region Fields
		private DesignerCanvas designerCanvas;
		#endregion

		#region Properties
		private List<ISelectable> currentSelection;
		internal List<ISelectable> CurrentSelection {
			get {
				if (currentSelection == null)
					currentSelection = new List<ISelectable>();

				return currentSelection;
			}
		}
		#endregion

		#region Constructors
		public SelectionService(DesignerCanvas canvas) {
			this.designerCanvas = canvas;
		}
		#endregion

		#region Methods
		internal void SelectItem(ISelectable item) {
			this.ClearSelection();
			this.AddToSelection(item);
		}

		internal void AddToSelection(ISelectable item) {
			if (item is IGroupable) {
				List<IGroupable> groupItems = GetGroupMembers(item as IGroupable);

				foreach (ISelectable groupItem in groupItems) {
					groupItem.IsSelected = true;
					CurrentSelection.Add(groupItem);
				}
			} else {
				item.IsSelected = true;
				CurrentSelection.Add(item);
			}
		}

		internal void RemoveFromSelection(ISelectable item) {
			if (item is IGroupable) {
				List<IGroupable> groupItems = GetGroupMembers(item as IGroupable);

				foreach (ISelectable groupItem in groupItems) {
					groupItem.IsSelected = false;
					CurrentSelection.Remove(groupItem);
				}
			} else {
				item.IsSelected = false;
				CurrentSelection.Remove(item);
			}
		}

		internal void ClearSelection() {
			CurrentSelection.ForEach(item => item.IsSelected = false);
			CurrentSelection.Clear();
		}

		internal void SelectAll() {
			ClearSelection();
			CurrentSelection.AddRange(designerCanvas.Children.OfType<ISelectable>());
			CurrentSelection.ForEach(item => item.IsSelected = true);
		}

		internal List<IGroupable> GetGroupMembers(IGroupable item) {
			IEnumerable<IGroupable> list = designerCanvas.Children.OfType<IGroupable>();
			IGroupable rootItem = GetRoot(list, item);
			return GetGroupMembers(list, rootItem);
		}

		internal IGroupable GetGroupRoot(IGroupable item) {
			IEnumerable<IGroupable> list = designerCanvas.Children.OfType<IGroupable>();
			return GetRoot(list, item);
		}

		private IGroupable GetRoot(IEnumerable<IGroupable> list, IGroupable node) {
			if (node == null || node.ParentID == Guid.Empty) {
				return node;
			} else {
				foreach (IGroupable item in list) {
					if (item.ID == node.ParentID) {
						return GetRoot(list, item);
					}
				}
				return null;
			}
		}

		private List<IGroupable> GetGroupMembers(IEnumerable<IGroupable> list, IGroupable parent) {
			List<IGroupable> groupMembers = new List<IGroupable>();
			groupMembers.Add(parent);

			var children = list.Where(node => node.ParentID == parent.ID);

			foreach (IGroupable child in children) {
				groupMembers.AddRange(GetGroupMembers(list, child));
			}

			return groupMembers;
		}
		#endregion		
	}
}
